package cn.ldf.keepaccounts.websocket;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.ldf.keepaccounts.constant.BaseConstant;
import cn.ldf.keepaccounts.entity.event.WsPushEvent;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ldf
 * @code May there be no bugs in the world!
 */
@Slf4j
@Component
@ServerEndpoint("/ws/rooms/{roomId}/{openId}")
public class RoomsWebsocket {
    /**
     * 收集房间和用户的会话
     */
    public static final Map<String, HashMap<String, Session>> SESSION_MAP = new ConcurrentHashMap<>();

    private String openId;
    private String roomId;

    @OnOpen
    public void onOpen(Session session) {
        roomId = session.getPathParameters().get(BaseConstant.ROOM_ID);
        openId = session.getPathParameters().get(BaseConstant.OPEN_ID);
        //一个房间多个用户的会话
        SESSION_MAP.computeIfAbsent(roomId, k -> new HashMap<>()).put(openId, session);
        log.info("用户openId:{},加入房间{}", openId, roomId);
    }

    @OnMessage
    public void onMessage(Session session, String message) {
        log.info("用户openId:{},在房间roomId:{},收到消息：{}", openId, roomId, message);
    }

    @OnClose
    public void onClose(Session session) {
        if (SESSION_MAP.containsKey(roomId)) {
            SESSION_MAP.get(roomId).remove(openId);
            log.info("用户openId:{},退出房间{}", openId, roomId);
        }
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        log.error("用户openId:{},在房间roomId:{},发生错误e:{}", openId, roomId, throwable.getMessage());
    }

    /**
     * 发送自定义消息到客户端
     */
    public static void sendInfo(WsPushEvent wsPushEvent, @PathParam("roomId") String roomId) {
        log.info("发送消息到,roomId:{},报文:{}", roomId, wsPushEvent);
        if (StrUtil.isNotBlank(roomId) && SESSION_MAP.containsKey(roomId)) {
            Map<String, Session> sessionMap = SESSION_MAP.get(roomId);
            sessionMap.forEach((openId, session) -> session.getAsyncRemote().sendText(JSONUtil.toJsonStr(wsPushEvent)));
        } else {
            log.error("房间不存在或已结算,roomId:{}", roomId);
        }
    }
}
